#!/usr/bin/env bash

__rvm_ruby_string_fuzzy_remote()
{
  \typeset new_ruby_string __search
  __search="${rvm_ruby_string}"
  if [[ -n "${rvm_ruby_name:-}" ]]
  then __search="${__search%${rvm_ruby_name:-}}.*${rvm_ruby_name:-}"
  fi
  new_ruby_string="$(
    __list_remote_all |
    __rvm_awk -F/ '{ x=$NF;
      gsub(".tar.*","",x);
      gsub("jruby-bin","jruby",x);
      gsub("rubinius","rbx",x);
      print x}' |
    __rvm_version_sort |
    __rvm_awk '
BEGIN{found=""; any=""}
/^'"${__search}"'$/ {found=$1}
/^'"${__search}"'/ {any=$1}
END{if (found) print found; else if (any) print any;}
'
  )"
  rvm_ruby_string="${new_ruby_string:-$rvm_ruby_string}"
}

__rvm_ruby_string_fuzzy()
{
  \typeset new_ruby_string __search
  __search="${rvm_ruby_string}"
  if [[ -n "${rvm_ruby_name:-}" ]]
  then __search="${__search%${rvm_ruby_name:-}}.*${rvm_ruby_name:-}"
  fi
  case "${__search}" in
    # If the pattern starts with one of the ruby names, don't search for the other rubies.
    (ruby*|rbx*|jruby*|truffleruby*|mruby*|macruby*|ree*|maglev*|ironruby*|opal*|topaz*)
      __search="^${__search}"
      ;;
  esac
  new_ruby_string="$(
    __rvm_list_strings |
    __rvm_grep "${__search//\./\\.}" |
    __rvm_version_sort |
    __rvm_tail -n 1
  )"
  if [[ -n "${new_ruby_string}" ]]
  then rvm_ruby_string="${new_ruby_string}"
  else return $?
  fi
}

__rvm_ruby_string_parse_()
{
  \typeset ruby_string gemset_name expanded_alias_name repo_url branch_name ruby_name tag_name

  # Stash the ruby string.
  ruby_string="${rvm_ruby_string:-}"
  gemset_name="${rvm_gemset_name:-}"
  repo_url="${rvm_ruby_repo_url:-}"
  branch_name="${rvm_ruby_repo_branch:-}"
  ruby_name="${rvm_ruby_name:-}"
  tag_name="${rvm_ruby_repo_tag:-}"

  __rvm_unset_ruby_variables

  rvm_ruby_repo_url="${repo_url:-}"
  rvm_ruby_repo_branch="${branch_name:-}"
  rvm_ruby_name="$ruby_name"
  rvm_ruby_repo_tag="${rvm_ruby_repo_tag:-}"

  export rvm_head_flag=0

  if
    [[ -z "${ruby_string}" || "${ruby_string}" == "current" ]]
  then
    if
      [[ "${GEM_HOME:-}" == *"${rvm_gems_path}"* ]]
    then
      # Current Ruby
      ruby_string="${GEM_HOME##*\/}"
      ruby_string="${ruby_string/%${rvm_gemset_separator:-"@"}*}"
    else
      ruby_string="system"
    fi
  fi

  strings=()
  __rvm_custom_separated_array strings - "${ruby_string}"
  rvm_ruby_string="${ruby_string}"

  # +() in ZSH, see https://github.com/rvm/rvm/issues/2807
  if [[ -n "${ZSH_VERSION:-}" ]]
  then setopt LOCAL_OPTIONS KSH_GLOB
  fi

  for string in ${strings[@]}
  do
    case "$string" in
      (head)
        rvm_ruby_patch_level=""
        rvm_ruby_revision=""
        rvm_ruby_tag=""
        rvm_head_flag=1
        ;;

      (system)
        rvm_ruby_interpreter="system"
        rvm_ruby_patch_level=""
        rvm_ruby_tag=""
        rvm_ruby_revision=""
        rvm_ruby_version=""
        rvm_gemset_name=""
        rvm_head_flag=0
        return 0
        ;;

      (ext|external)
        rvm_ruby_interpreter="ext"
        rvm_ruby_patch_level=""
        rvm_ruby_tag=""
        rvm_ruby_revision=""
        rvm_ruby_version=""
        rvm_head_flag=0

        rvm_ruby_name="${ruby_string:-${rvm_ruby_string}}"
        rvm_ruby_name="${rvm_ruby_name#*-}"
        break
        ;;

      (nightly|weekly|monthly)
        case "${rvm_ruby_interpreter}" in
          (rbx|rubinius) rvm_ruby_patch_level="$string" ;;
          (*)            rvm_ruby_version="$string"     ;;
        esac
        rvm_nightly_flag=1
        ;;

      (nightly*|weekly*|monthly*)
        case "${rvm_ruby_interpreter}" in
          (rbx|rubinius) rvm_ruby_patch_level="$string" ;;
          (*)            rvm_ruby_version="$string"     ;;
        esac
        ;;

      (preview*)
        rvm_ruby_patch_level="$string"
        ;;

      (rc[0-9]*)
        rvm_ruby_patch_level="$string"
        ;;

      (+([0-9]).+([0-9]).[0-9]*)
        rvm_ruby_version="${string}"
        rvm_ruby_revision=""
        rvm_ruby_tag=""
        ;;

      ([0-9][0-9]*)
        case "${rvm_ruby_interpreter:-""}" in
          (ree)
            rvm_ruby_patch_level="$string"
            rvm_ruby_revision=""
            ;;
          (maglev)
            rvm_ruby_version="$string"
            rvm_ruby_revision=""
            rvm_ruby_patch_level=""
            ;;
          (*)
            rvm_ruby_version="${string}"
            rvm_ruby_revision=""
            rvm_ruby_tag=""
            ;;
        esac
        ;;

      ([0-9]*)
        rvm_ruby_version="${string}"
        rvm_ruby_revision=""
        rvm_ruby_tag=""
        ;;

      (p[0-9]*)
        rvm_ruby_patch_level="$string"
        ;;

      (r[0-9]*)
        rvm_ruby_patch_level=""
        rvm_ruby_revision="$string"
        ;;

      (s[0-9a-zA-ZuU]*)
        rvm_ruby_revision=""
        rvm_ruby_sha="${string#s}"
        ;;

      (tag[0-9])
        rvm_ruby_repo_tag="$string"
        ;;

      (tv[0-9]*|t[0-9]*)
        rvm_ruby_patch_level="" ; rvm_ruby_revision=""
        rvm_ruby_tag="$string"
        ;;

      (m[0-9]*)
        rvm_ruby_mode="$string"
        ;;

      (u[0-9a-zA-ZuU]*)
        rvm_ruby_patch_level="" ; rvm_ruby_revision="" ; rvm_ruby_tag="" ; rvm_ruby_patch=""
        rvm_ruby_user_tag="$string"
        ;;

      (b[0-9]*)
        rvm_ruby_repo_branch="${string}"
        rvm_head_flag=1
        ;;

      (rubinius)
        rvm_ruby_interpreter="rbx"
        ;;

      (opal|ruby|rbx|jruby|macruby|ree|maglev|ironruby|mruby|topaz|truffleruby)
        rvm_ruby_interpreter="$string"
        ;;

      ([a-zA-ZuU]*([0-9a-zA-ZuU]|_))
        rvm_ruby_name="$string"
        ;;

      (*)
        rvm_ruby_string="${ruby_string:-}"
        return 0
        ;;
    esac
  done
  if
    [[ -z "${rvm_ruby_interpreter}" && -n "${rvm_ruby_version}" ]]
  then
    case "${rvm_ruby_version}" in
      (1.[5-7]*|9*)    rvm_ruby_interpreter=jruby ;;
      (1.[8-9]*|2*|3*) rvm_ruby_interpreter=ruby  ;;
    esac
    if [[ -n "${rvm_ruby_interpreter}" ]]
    then rvm_ruby_string="${rvm_ruby_interpreter}-${rvm_ruby_string}"
    fi
  fi
  true # OSX --trace FIX
}

__rvm_ruby_string_latest()
{
  \typeset check_ruby_string new_ruby_string
  check_ruby_string=""
  if [[ -n "${rvm_ruby_interpreter}" ]]
  then check_ruby_string+="^${rvm_ruby_interpreter}-"
  fi
  if [[ -n "${rvm_ruby_version}" ]]
  then check_ruby_string+="${rvm_ruby_version//\./\.}.*"
  fi
  if [[ -n "${rvm_ruby_patch_level}" ]]
  then check_ruby_string+="${rvm_ruby_patch_level//\./\.}.*"
  fi
  if [[ -z "${check_ruby_string}" ]]
  then check_ruby_string="$rvm_ruby_string"
  fi
  new_ruby_string="$(
    \command \cat "$rvm_path/config/known_strings" |
    __rvm_grep "${check_ruby_string}" |
    __rvm_version_sort |
    __rvm_tail -n 1
  )"
  if
    [[ -n "${new_ruby_string}" ]]
  then
    rvm_ruby_string="${new_ruby_string}"
  else
    rvm_error "Unknown ruby string (do not know how to handle): $rvm_ruby_string."
    return 1
  fi
}

__rvm_ruby_string_parse()
{
  # detect rvm_ruby_name early so it can be used in fuzzy/remote
  __rvm_ruby_string_parse_ || true

  if
    (( ${rvm_fuzzy_flag:-0} == 1 )) &&
    [[ ! -d "${rvm_rubies_path}/${rvm_ruby_string}" ]]
  then
    if
      (( ${rvm_remote_flag:-0} == 1 ))
    then
      __rvm_ruby_string_fuzzy        ||
      __rvm_ruby_string_fuzzy_remote ||
      return $?
    else
      __rvm_ruby_string_fuzzy || true
    fi
  fi

  # parse the detected version
  __rvm_ruby_string_parse_ || return $?

  if
    [[ -z "${rvm_ruby_interpreter}" ]]
  then
    rvm_error "Unknown ruby interpreter version (do not know how to handle): $rvm_ruby_string."
    return 1
  fi
}
